package iotwisp.base.cqrs.unitofwork;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import iotwisp.base.cqrs.BaseCommand;
import iotwisp.base.jwt.JwtConfig;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;

import lombok.extern.slf4j.Slf4j;

/**
 * 切点类
 * 
 * @author yuxx
 * @since 2014-08-05 Pm 20:35
 * @version 1.0
 */
@Slf4j
@Aspect
@Component
public class UnitOfWorkAspect {

	@Autowired
	private JwtConfig jwtConfig;
	@Value("${server.port}")
	private String port;

	// Service层切点
	@Pointcut("@annotation(iotwisp.base.cqrs.unitofwork.UseUnitOfWork)")
	public void serviceAspect() {
	}

	@Before("serviceAspect()")
	public void doBefore(JoinPoint joinPoint) {
		Object[] arguments = joinPoint.getArgs();
		if (arguments != null && arguments.length > 0) {
			BaseCommand command = (BaseCommand) arguments[0];
			log.info("开始处理命令:{} / {}", System.currentTimeMillis(), JSON.toJSONString(command));
		}
	}

	@After("serviceAspect()")
	public void doAfter(JoinPoint joinPoint) {
		Object[] arguments = joinPoint.getArgs();
		if (arguments != null && arguments.length > 0) {
			BaseCommand command = (BaseCommand) arguments[0];
			log.info("结束处理命令:{} / {}", System.currentTimeMillis(), JSON.toJSONString(command));
		}

	}

	/**
	 * 用于拦截service层记录业务事件日志
	 * 
	 * @param joinPoint
	 * @param e
	 */
	@AfterThrowing(pointcut = "serviceAspect()", throwing = "e")
	public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {

		Object[] arguments = joinPoint.getArgs();
		if (arguments != null && arguments.length > 0) {
			BaseCommand command = (BaseCommand) arguments[0];

			if (command.getCleanUnitOfWork()) {
//				command.getUnitOfWork().publish(true);
			}

		}
	}

	/**
	 * 获取注解中对方法的描述信息 用于service层注解
	 * 
	 * @param joinPoint 切点
	 * @return 方法描述
	 * @throws Exception
	 */
	public static String getServiceMthodDescription(JoinPoint joinPoint) throws Exception {
		String targetName = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		Object[] arguments = joinPoint.getArgs();
		Class<?> targetClass = Class.forName(targetName);
		Method[] methods = targetClass.getMethods();
		String description = "";
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				Class<?>[] clazzs = method.getParameterTypes();
				if (clazzs.length == arguments.length) {
					description = method.getAnnotation(UseUnitOfWork.class).description();
					break;
				}
			}
		}
		return description;
	}

	/**
	 * 获取注解中对方法的描述信息 用于service层注解
	 * 
	 * @param joinPoint 切点
	 * @return 方法描述
	 * @throws Exception
	 */
	public static Map<String, String> getServiceMthodInfo(JoinPoint joinPoint) throws Exception {
		String targetName = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		Object[] arguments = joinPoint.getArgs();
		Class<?> targetClass = Class.forName(targetName);
		Method[] methods = targetClass.getMethods();
		Map<String, String> map = new HashMap<>();
		String description = "";
		String operateType = "";
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				Class<?>[] clazzs = method.getParameterTypes();
				if (clazzs.length == arguments.length) {
					description = method.getAnnotation(UseUnitOfWork.class).description();
					operateType = method.getAnnotation(UseUnitOfWork.class).operateType().toString();
					map.put("description", description);
					map.put("operateType", operateType);
					break;
				}
			}
		}
		return map;
	}

}